package xml.resource;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ResourceException;
import xml.converter.AbstractJDOMElementRepresentationConverter;
import xml.hcard.HCARDFactory;
import xml.hcard.RemoteHCARDFactory;
import xml.model.Promotion;
import xml.model.User;
import xml.validator.LengthValidator;
import xml.validator.LongRangeValidator;
import xml.validator.NotEmptyValidator;
import xml.validator.URIValidator;

/**
 * Resource représentant les promotions d'un utilisateur
 * Méthodes: GET POST
 * @author marya
 */
public class PromotionsResource extends AbstractResource {

    private User user;

    public PromotionsResource() {
        super();
    }

    @Override
    public void doInit() {
        Long idUser = null;
        final String sqlSession = "SELECT id_user FROM user WHERE id_user = ";
        String idUserAttribute = getRequest().getAttributes().get("idUser").toString();
        LongRangeValidator longRangeValidator = new LongRangeValidator(1l, null);
        Connection connexion = null;
        //Validation de l'id de la session
        if (longRangeValidator.isValid(idUserAttribute)) {
            idUser = Long.parseLong(idUserAttribute);
        } else {
            throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "invalidIdUser");
        }
        //Vérification d'existence de l'utilisateur
        try {
            connexion = database.getNewConnection();
            ResultSet rs = connexion.createStatement().executeQuery(sqlSession + idUser);
            if (!rs.next()) {
                setExisting(false);
            } else {
                user = new User(rs.getInt("id_user"));
            }
            connexion.close();
        } catch (SQLException ex) {
            throw new ResourceException(Status.SERVER_ERROR_INTERNAL, ex);
        }

    }

    @Get
    public Representation doGet() throws Exception {
        Representation response = null;
        List<Promotion> promotions = new ArrayList<Promotion>();
        Promotion p = null;
        Connection connexion = null;
        ResultSet rs = null;
        final String sqlPromotion = " SELECT id_groupe,nom FROM groupe WHERE id_user = " + user.getIdUser() + " AND url IS NOT NULL";
        try {
            connexion = database.getNewConnection();
            rs = connexion.createStatement().executeQuery(sqlPromotion);
            while (rs.next()) {
                p = new Promotion(rs.getInt("id_groupe"), rs.getString("nom"), null);
                p.setUri(getRootRef().getHostIdentifier() + "/promotions/" + p.getIdGroupe());
                promotions.add(p);
            }
            connexion.close();
            response = (new AbstractJDOMElementRepresentationConverter()).convert(promotions);
        } catch (SQLException e) {
            DbUtils.closeQuietly(rs);
            DbUtils.closeQuietly(connexion);
            throw e;
        }
        return response;
    }

    @Post
    public Representation doPost(Representation entity) throws Exception {
        Representation response = null;
        xml.form.Form form = getNewForm(entity);
        System.out.println(entity.getText());
        final String sqlPromotion = "INSERT INTO groupe(id_user,nom,url) VALUES(?,?,?)";
        Connection connexion = null;

        //Mettre ici un formulaire validable à implémenter
        try {
            if (!form.isValid()) {
                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                for (String error : form.getMessages()) {
                    errors.add(new ResourceError(error));
                }
            } else {
                String url = form.getFirstValue("uriPromotion");
                String nom = form.getFirstValue("nomPromotion");
                HCARDFactory hF = new RemoteHCARDFactory(url);

                if (hF.start().toXML() == null) {
                    setStatus(Status.SERVER_ERROR_BAD_GATEWAY);
                    errors.add(new ResourceError("Can not handle request due to response null"));
                } else {
                    connexion = database.getNewConnection();
                    QueryRunner queryRunner = new QueryRunner();
                    PreparedStatement preparedStatement = connexion.prepareStatement(sqlPromotion, PreparedStatement.RETURN_GENERATED_KEYS);
                    queryRunner.fillStatement(
                            preparedStatement,
                            user.getIdUser(), nom, url);
                    preparedStatement.executeUpdate();
                    ResultSet rs = preparedStatement.getGeneratedKeys();
                    rs.next();
                    Integer result = rs.getInt(1);
//                    QueryRunner qR = new QueryRunner();
//                    Integer result = qR.update(connexion, sqlPromotion, user.getIdUser(), nom, url);
                    Promotion p = new Promotion(result, nom, null);
                    p.setUri(getRootRef().getHostIdentifier() + "/promotions/" + result);
                    response = p.toXML();
                    setStatus(Status.SUCCESS_CREATED);
                }
            }
            DbUtils.closeQuietly(connexion);
        } catch (Exception e) {
            setStatus(Status.SERVER_ERROR_BAD_GATEWAY);
            throw e;
        }
        if (!errors.isEmpty()) {
            response = ResourceError.getListRepresentation(errors);
        }
        return response;
    }

    @SuppressWarnings("unchecked")
    private xml.form.Form getNewForm(Representation entity) {
        xml.form.Form form = new xml.form.Form(entity);
        NotEmptyValidator notEmptyValidator = new NotEmptyValidator();
        form.addValidators("nomPromotion", notEmptyValidator, new LengthValidator(255));
        form.addValidators("uriPromotion", notEmptyValidator, new URIValidator());
        return form;
    }

    @Override
    protected void doCatch(Throwable throwable) {
        super.doCatch(throwable);
        throwable.printStackTrace();
    }
}
